package org.freespace.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.freespace.config.GlobalConf;
import org.freespace.model.EnvironmentMachine;
import org.freespace.model.Job;
import org.freespace.model.JobMachine;
import org.freespace.service.IEnvironmentMachineService;
import org.freespace.service.IJobMachineService;
import org.freespace.service.IJobService;
import org.freespace.service.IMonitorSerivce;
import org.freespace.utils.InfluxDBUtils;
import org.freespace.utils.SpringBeanUtil;
import org.freespace.vo.MonitorUrlVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class MonitorSerivceImpl implements IMonitorSerivce {

    @Value("${linuxServerUrl}")
    private String linuxServerUrl;

    @Value("${stressMachineUrl}")
    private String stressMachineUrl;

    @Autowired
    IEnvironmentMachineService environmentMachineService;
    @Autowired
    IJobMachineService jobMachineService;

    @Autowired
    IJobService jobService;

    @Autowired
    InfluxDBUtils influxDBUtils;
    
    @Override
    public List<MonitorUrlVO> monitorUrlList(Integer jobId, String envId) {
        List<MonitorUrlVO> monitorUrlVOList = new ArrayList<>();

        Job job = jobService.getById(jobId);

        LocalDateTime startTime = job.getStartTime();
        LocalDateTime endTime = Optional.ofNullable(job.getEndTime()).orElse(LocalDateTime.now());

        long startTimeStamp = startTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
        long endTimeStamp = endTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();

        // 被压测服务相关机器的监控页面
        MonitorUrlVO appServerGrafanaUrl = getAppServerGrafanaUrl(jobId, startTimeStamp, endTimeStamp);
        if (appServerGrafanaUrl != null) {
            monitorUrlVOList.add(appServerGrafanaUrl);
        }

        // 场景关联环境的所有linux机器的服务器的监控页面
        MonitorUrlVO linnuxServerGrafanaUrl = getLinuxServerGrafanaUrl(jobId, startTimeStamp, endTimeStamp, envId);
        if (linnuxServerGrafanaUrl != null) {
            monitorUrlVOList.add(linnuxServerGrafanaUrl);
        }

        // job关联环境的所有压力机机器的服务器的监控页面
        MonitorUrlVO stressMachineGrafanaUrl = getStressMachineGrafanaUrl(jobId, startTimeStamp, endTimeStamp);
        if (linnuxServerGrafanaUrl != null) {
            monitorUrlVOList.add(stressMachineGrafanaUrl);
        }

        return monitorUrlVOList;
    }

    private MonitorUrlVO getStressMachineGrafanaUrl(Integer jobId, long startTimeStamp, long endTimeStamp) {
        LambdaQueryWrapper<JobMachine> wrapper = Wrappers.<JobMachine>lambdaQuery().eq(JobMachine::getJobId, jobId);
        List<JobMachine> machineList = jobMachineService.list(wrapper);
        if (CollectionUtil.isEmpty(machineList)) {
            return null;
        }
        StringBuffer url = new StringBuffer();
        url.append(stressMachineUrl)
                .append(jobId)
                .append("&var-prometheus_ds=Prometheus&var-influxdb_ds=InfluxDB")
                .append("&from=").append(startTimeStamp)
                .append("&to=").append(endTimeStamp);
        MonitorUrlVO monitorUrlVO = new MonitorUrlVO();
        monitorUrlVO.setType("StressMachine");
        monitorUrlVO.setUrl(url.toString());
        return monitorUrlVO;
    }

    private MonitorUrlVO getLinuxServerGrafanaUrl(Integer jobId, long startTimeStamp, long endTimeStamp, String envId) {
        LambdaQueryWrapper<EnvironmentMachine> wrapper = Wrappers.<EnvironmentMachine>lambdaQuery().eq(EnvironmentMachine::getEnvId, envId).eq(EnvironmentMachine::getOs, "linux");
        List<EnvironmentMachine> environmentMachineList = environmentMachineService.list(wrapper);
        if (CollectionUtil.isEmpty(environmentMachineList)) {
            return null;
        }
        StringBuffer url = new StringBuffer();
        url.append(linuxServerUrl)
                .append(envId)
                .append("&var-prometheus_ds=Prometheus&var-influxdb_ds=InfluxDB")
                .append("&var-jobId=").append(jobId)
                .append("&from=").append(startTimeStamp)
                .append("&to=").append(endTimeStamp);
        MonitorUrlVO monitorUrlVO = new MonitorUrlVO();
        monitorUrlVO.setType("LinuxServer");
        monitorUrlVO.setUrl(url.toString());
        return monitorUrlVO;
    }

    /**
     * 被压测服务相关机器的监控页面
     * @param jobId
     * @param startTimeStamp
     * @param endTimeStamp
     * @return
     */
    private MonitorUrlVO getAppServerGrafanaUrl(Integer jobId, long startTimeStamp, long endTimeStamp) {
        StringBuffer url = new StringBuffer();
        url.append(influxDBUtils.getPerformanceUrl(jobId))
                .append(jobId)
                .append("&var-time=").append(startTimeStamp)
                .append("&from=").append(startTimeStamp)
                .append("&to=").append(endTimeStamp);
        MonitorUrlVO monitorUrlVO = new MonitorUrlVO();
        monitorUrlVO.setType("AppServer");
        monitorUrlVO.setUrl(url.toString());
        return monitorUrlVO;
    }
}
